package relu.fbs.xt;

import java.io.*;
import java.util.*;

import relu.fbs.BadDataException;
import relu.fbs.FBSDataType;

public class FBSYearData {

	public Map<Integer,FBSFarmData> farms=new HashMap<Integer,FBSFarmData>();
	private FBSYearDataFileHandle fileHandle =null;
	
	/** Used when initializing from a csv file */
	private class FBSYearDataFileHandle {
		private final BufferedReader reader;
		private String currentLine;
		FBSYearDataFileHandle(String fileName) {
			try {
				reader=new BufferedReader(new FileReader(fileName));
				String header = reader.readLine();
				if ( !FBSFarmData.checkCSVHeader(header)){
					throw new Error("File "+fileName+" has the wrong header ");
				}
			} catch (FileNotFoundException ex){
				throw new Error(ex.getMessage());
			} catch (IOException ex){
				throw new Error(ex.getMessage());
			}
		}
		FBSFarmData getNextFarm() throws IOException {
			currentLine=reader.readLine();
			if ( currentLine!=null){
				FBSFarmData currentFarm = new FBSFarmData(currentLine);
//				farms.put((Integer)(currentFarm.farmId),currentFarm);
				return currentFarm;
			} else {
				return null;
			}
		}

	}

	public	void addData(FBSDataType type,BufferedReader input) throws IOException ,NumberFormatException {		
		switch(type.format){
		case POST2000:
			readPost2000Data(input);
			break;
		default:
			throw new Error("No reader defined for format "+type.format);			
		}
	}
	
	public	void addData(int dataYear) throws IOException ,NumberFormatException ,BadDataException{		
		switch(dataYear){
		case 1998:
			farms.putAll(FBS8898DataReader.read98Data());
			break;
		case 1997:
			farms.putAll(FBS8898DataReader.read97Data());
			break;
		case 1996:
			farms.putAll(FBS8898DataReader.read96Data());
			break;
		case 1995:
			farms.putAll(FBS8898DataReader.read95Data());
			break;
		case 1994:
			farms.putAll(FBS8898DataReader.read94Data());
			break;
		case 1993:
			farms.putAll(FBS8898DataReader.read93Data());
			break;
		case 1992:
			farms.putAll(FBS8898DataReader.read92Data());
			break;
		case 1991:
			farms.putAll(FBS8898DataReader.read91Data());
			break;
		case 1990:
			farms.putAll(FBS8898DataReader.read90Data());
			break;
		case 1989:
			farms.putAll(FBS8898DataReader.read89Data());
			break;
		case 1988:
			farms.putAll(FBS8898DataReader.read88Data());
			break;
		case 1987:
			farms.putAll(FBS8387DataReader.read87Data());
			break;
		case 1986:
			farms.putAll(FBS8387DataReader.read86Data());
			break;
		case 1985:
			farms.putAll(FBS8387DataReader.read85Data());
			break;
		case 1984:
			farms.putAll(FBS8387DataReader.read84Data());
			break;
		default:
			throw new Error("No reader defined for year "+dataYear);			
		}
	}
	
	/** Write this year worth of data to a csv file */
	public void writeAllToCSV(String fileName) throws IOException {
		FileWriter writer=new FileWriter(fileName);
		writer.write(FBSFarmData.allToCSVHeader());
		for ( FBSFarmData fd:farms.values()){
			fd.writeAllToCSV(writer);
		}
		writer.close();
	}
	
	public FBSYearData(){};
	public static FBSYearData fromCSV(String fileName,boolean readAll){
		FBSYearData dat;
		dat=new FBSYearData(fileName,readAll);
		return dat;
	}
	public FBSFarmData nextFarm() throws IOException , BadDataException {
		if ( fileHandle == null ){			
			throw new Error("No filehandle has been initialized for this FBSYearData object");
		}
		return fileHandle.getNextFarm();
	}
	
	/** Initialize this object by reading a csv file */	
	private FBSYearData(String fileName,boolean readAll){
		try {
			if ( readAll ){
				FileReader reader =new FileReader(fileName);
				BufferedReader buffrd=new BufferedReader(reader);
				initFromCSV(buffrd);
			} else {
				fileHandle=new FBSYearDataFileHandle(fileName);
			}
		} catch (IOException ex){
			throw new Error(ex.getMessage());
		}
	}
	
	
	private void initFromCSV(BufferedReader input) throws IOException {
		String header = input.readLine();
		int numLines=0;
		if ( FBSFarmData.checkCSVHeader(header)){
			String line=input.readLine();
			while ( line!=null){
				FBSFarmData currentFarm = new FBSFarmData(line);
				farms.put((Integer)(currentFarm.farmId),currentFarm);
				line=input.readLine();
				numLines++;
//				System.out.println("Line "+numLines);
			}
		} else {
			throw new Error("Header for this csv file is incompatible with data format");
		}
	}
	
	private void readPost2000Data(BufferedReader input) throws IOException, NumberFormatException {
		int lineNum=0;
		int numFarmsDone=0;
		String line=input.readLine();
		FBSFarmData currentFarm=new FBSFarmData(-1); // First farm is a dummy with no farm id
		int errLines=0;
		List<String> farmLines = new ArrayList<String>();
		while(line !=null){
			String[] colStrings=line.split("\t");
			if ( colStrings.length != FBSDataType.Format.POST2000.ncols){
				errLines++;
				if ( errLines > 3 ){
					throw new Error("Badly formatted file has only "+colStrings.length+" cols \n"+line);
				}
			} else {
				int farmId=Integer.parseInt(colStrings[0]);
				colStrings[1]=colStrings[1].replaceAll("\"", "");
				char section=colStrings[1].charAt(0);
				int row=Integer.parseInt(colStrings[2]);
				int col=Integer.parseInt(colStrings[3]);
				int ctype=Integer.parseInt(colStrings[4]);
				int etype=Integer.parseInt(colStrings[5]);
				double value=Double.parseDouble(colStrings[7]);
//				System.out.println(farmId+" "+section+" "+row+" "+col+" "+ctype+" "+value);
				if ( currentFarm.farmId != farmId){
//					currentFarm.calculateSummaryData();
					currentFarm=new FBSFarmData(farmId);
					farms.put(farmId, currentFarm);
					numFarmsDone++;
//					System.out.println(numFarmsDone);
					farmLines.clear();
				}		
				try {
				currentFarm.addPost2000Datum(new FBSPost2000DataPoint(farmId,section,row,col,ctype,etype),value);
				} catch (BadDataException ex){
					for(String ln:farmLines){
						System.out.println(ln);
					}
					throw new Error(ex.getMessage()+" Farm "+farmId+" failed ");
				}
			}
			lineNum++;
			line=input.readLine();
			farmLines.add(line);
		}
	}
	
}
